<?php

namespace app\service;

use app\model\ProjectModel;
use app\model\TaskModel;
use app\model\TaskWorkOrderModel;
use app\model\TaskWorkOrderProblemStepCategoryModel;
use app\model\TaskWorkOrderUserModel;
use app\tool\SingletonTrait;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class TaskWorkOrderReportService
{
    use SingletonTrait;

    public ProjectModel $projectModel;
    public TaskModel $taskModel;
    public TaskWorkOrderModel $taskWorkOrderModel;
    public TaskWorkOrderUserModel $taskWorkOrderUserModel;
    public TaskWorkOrderProblemStepCategoryModel $taskWorkOrderProblemStepCategoryModel;

    // 工单处理状态(0:未处理,1:已处理,2:已失效,3:处理中)
    public const TASK_WORD_ORDER_STATUS_NOT_PROCESSED = 0;
    public const TASK_WORD_ORDER_STATUS_PROCESSED = 1;
    public const TASK_WORD_ORDER_STATUS_EXPIRED = 2;
    public const TASK_WORD_ORDER_STATUS_PROCESSING = 3;

    // 查询指定状态下的工单数据
    public array $taskWorkOrderStatusDefault = [
        self::TASK_WORD_ORDER_STATUS_NOT_PROCESSED,
        self::TASK_WORD_ORDER_STATUS_PROCESSED,
        self::TASK_WORD_ORDER_STATUS_PROCESSING
    ];

    public function __construct()
    {
        $this->projectModel = new ProjectModel();
        $this->taskModel = new TaskModel();
        $this->taskWorkOrderModel = new TaskWorkOrderModel();
        $this->taskWorkOrderProblemStepCategoryModel = new TaskWorkOrderProblemStepCategoryModel();
        $this->taskWorkOrderUserModel = new TaskWorkOrderUserModel();
    }

    // 工单统计必传的字段
    protected array $taskWorkOrderField = [
        "task_work_order.id",
        "task_work_order.status",
        "task_work_order.report_type",
        "task_work_order.task_id",
        "task_work_order.project_id",
        "task_work_order.entity_id",
        "task_work_order.step_category_id",
        "task_work_order.category_id",
        "task_work_order.created",
    ];
    // 定义工单初始化统计数量
    protected array $taskWorkOrderCount = [
        "not_processed" => [
            'status' => self::TASK_WORD_ORDER_STATUS_NOT_PROCESSED,  // 未处理
            'number' => 0,
            "name" => "未处理"
        ],
        "processed" => [
            'status' => self::TASK_WORD_ORDER_STATUS_PROCESSED, // 已处理
            'number' => 0,
            "name" => "已处理"
        ],
        "processing" => [
            'status' => self::TASK_WORD_ORDER_STATUS_PROCESSING, // 处理中
            'number' => 0,
            "name" => "处理中"
        ],
        // 工单总数
        "total_number" => [
            'status' => 'all',  // 全部工单数
            "number" => 0,
            "name" => "全部工单"
        ]
    ];


    /**
     * 获取工单报表
     * @param int $tenantId 租户id
     * @param array $projectIds 项目id
     * @param array $stepCategoryId 工序分类id
     * @param array $categoryId 分类id
     * @param array $page 分页条件 [1,100]
     * @param array $time 时间范围[开始时间,结束时间]
     * @return array [{"参数1":"返回值"}]
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getTaskWorkOrderReports(
        int $tenantId,
        array $projectIds,
        array $page,
        array $time,
        array $stepCategoryId = [],
        array $categoryId = []
    ): array {

        // 固定查询条件
        $condition = [
            "task_work_order.tenant_id" => $tenantId,
            "task_work_order.type" => "task_making",
            "task_work_order.status" => $this->taskWorkOrderStatusDefault
        ];
        //组装工单查询条件 按环节查询条件
        $this->searchTaskWorkOrderStepCategoryQuery($condition, $stepCategoryId);
        // 组装工单查询条件 按分类id 进行查找
        $this->searchTaskWorkOrderCategoryIdQuery($condition, $categoryId);
        //构建项目查找条件 按项目id进行查找
        $this->getProjectWhereQuery($condition, $projectIds);
        // 组装指定的时间查询条件
        [$startTime, $endTime] = $time;
        //返回查询的结果数据
        $result = $this->taskWorkOrderModel->field($this->taskWorkOrderField)
            ->where($condition)
            ->whereBetweenTime('task_work_order.created', $startTime, $endTime)
            ->order('task_work_order.id', 'desc')
            ->paginate([
                'page' => $page[0], // 当前页码
                'list_rows' => $page[1], // 每页数量
            ]);
        unset($condition);
        if (empty($result)) {
            return [];
        }

        return [
            'total' => $result->total(), //总条数
            'num_page' => $page[1], //每页显示条数
            'current_page' => $result->currentPage(),//当前页
            'last_page' => $result->lastPage(),//最后一页
            'data' => $result->items(), // 数据
        ];
    }


    /**
     * 组装工单查询条 按项目id进行查找
     * @param array $condition
     * @param array $projectIds 指定的项目id
     */
    private function getProjectWhereQuery(array &$condition, array $projectIds)
    {
        //组装工单查询条件 按多个项目id进行查找
        if (!empty($projectIds)) {
            $condition["task_work_order.project_id"] = $projectIds;
        }
        return $condition;
    }


    /**
     * 统计不同状态下的工单数据
     * @param int $tenantId
     * @param array $projectIds
     * @param array $createTime
     * @param array $stepCategoryId
     * @return array [{"参数1":"参数值" ...}]
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function countTaskWorkOrderNumberDiffByStatus(
        int $tenantId,
        array $projectIds,
        array $createTime,
        array $stepCategoryId = []
    ): array
    {
        //组装查询条件 租户信息 工单类型 工单状态
        $condition = [
            "task_work_order.tenant_id" => $tenantId,
            "task_work_order.type" => "task_making",
            "task_work_order.status" => $this->taskWorkOrderStatusDefault
        ];
        // 组装指定工序环节条件
        $this->searchTaskWorkOrderStepCategoryQuery($condition, $stepCategoryId);
        // 组装指定项目
        $this->getProjectWhereQuery($condition, $projectIds);
        // 组装指定时间条件
        [$startTime, $endTime] = $createTime;
        $result = $this->taskWorkOrderModel->field($this->taskWorkOrderField)
            ->where($condition)
            ->whereBetweenTime('task_work_order.created', $startTime, $endTime)
            ->order('task_work_order.id', 'desc')
            ->select();
        unset($condition);
        // 定义默认参数
        $taskWorkOrderCount =  $this->taskWorkOrderCount;
        // 如果工单数量不存,返回缺省值
        if(empty($result)){
            return $taskWorkOrderCount;
        }

        foreach ($result->toArray() as $value){
            if((int)$value["status"] === self::TASK_WORD_ORDER_STATUS_NOT_PROCESSED ){
                $taskWorkOrderCount["processed"]["number"] += 1;
            }
            if((int)$value["status"] === self::TASK_WORD_ORDER_STATUS_PROCESSED ){
                $taskWorkOrderCount["not_processed"]["number"] += 1;
            }
            if((int)$value["status"] === self::TASK_WORD_ORDER_STATUS_PROCESSING ){
                $taskWorkOrderCount["processing"]["number"] += 1;
            }
            $taskWorkOrderCount["total_number"]["number"] += 1;
        }
        return $taskWorkOrderCount;
    }

    /**
     * 返回指定环节的工单占比数据
     * @param int $tenantId
     * @param array $projectIds
     * @param array $createdTime
     * @param array $stepCategoryId
     * @return array [{"参数1":"参数值" ...}]
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function countTaskWorkOrderProportion(
        int $tenantId,
        array $projectIds,
        array $createdTime,
        array $stepCategoryId = []
    ): array
    {
        $condition = [
            "task_work_order.tenant_id" => $tenantId,
            "task_work_order.type" => "task_making",
            "task_work_order.status" => $this->taskWorkOrderStatusDefault
        ];
        // 组装指定环节参数
        $this->searchTaskWorkOrderStepCategoryQuery($condition, $stepCategoryId);
        // 组装指定项目参数
        $this->getProjectWhereQuery($condition, $projectIds);
        [$startTime, $endTime] = $createdTime;

        $result = $this->taskWorkOrderModel
            ->field($this->taskWorkOrderField)
            ->where($condition)
            ->whereBetweenTime('task_work_order.created', $startTime, $endTime)
            ->order('task_work_order.id', 'desc')
            ->select();

        unset($condition);
        if(empty($result)){
            return [];
        }

        return $result->toArray();
    }


    /**
     * 组装工单数据 按工序分类条件进行筛选
     * @param array $condition 条件数组
     * @param array $stepCategoryId 工序分类id
     */
    private function searchTaskWorkOrderStepCategoryQuery(array &$condition, array $stepCategoryId)
    {
        //组装工单数据 按分类条件进行筛选
        if (!empty($stepCategoryId)) {
            $condition["task_work_order.step_category_id"] = $stepCategoryId;
        }

    }

    /**
     * 组装工单数据 按分类条件进行筛选
     * @param array $condition 条件数组
     * @param array $categoryId 分类id数据
     */
    private function searchTaskWorkOrderCategoryIdQuery(array &$condition,array $categoryId)
    {
        //组装工单数据 按分类条件进行筛选
        if (!empty($categoryId)) {
            $condition["task_work_order.category_id"] =  $categoryId;
        }
    }


    /**
     * 获取本周的开始时间和结束时间
     * @return array
     */
    private function getWeekStartAndEndTime(): array
    {
        //设置时间区(中国)
        date_default_timezone_set('Asia/Shanghai');
        $weekStart = strtotime(date('Y-m-d', strtotime('this week Monday')));
        $weekEnd = strtotime(date('Y-m-d 23:59:59', strtotime('this Sunday')));

        return ['week_start_time' => $weekStart,'week_end_time' => $weekEnd];
    }

    /**
     * 统计不同环节下的工单问题数据
     * @param array $projectId
     * @param int $tenantId
     * @param array $time
     * @param array $stepCategoryId
     * @return array
     */
    public function countTaskWorkOrderByStepCategoryId(array $projectId, int $tenantId, array $time, array $stepCategoryId = []) : array
    {
        $condition = [
            "task_work_order.tenant_id" => $tenantId,
            "task_work_order.type" => "task_making",
            "task_work_order.status" => $this->taskWorkOrderStatusDefault
        ];
        //组装工单查询条件 按环节查询条件
        $this->searchTaskWorkOrderStepCategoryQuery($condition, $stepCategoryId);
        //组装指定的项目
        $this->getProjectWhereQuery($condition, $projectId);
        // 组装指定时间条件
        [$startTime, $endTime] = $time;
        // 查询数据
        $result = $this->taskWorkOrderModel->field("step_category_id,report_type,count(distinct id) num")
            ->where($condition)
            ->whereBetweenTime('task_work_order.created', $startTime, $endTime)
            ->group("step_category_id,report_type")
            ->select();
        if(empty($result)){
            return [];
        }

        return $result->toArray();

    }

}
